package org.flynenu.core.util;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections.FastHashMap;

public class EntityUtil {

    private static final FastHashMap fieldsMap = new FastHashMap();

    private static final FastHashMap allMethods = new FastHashMap();
    static {
        fieldsMap.setFast(true);
        allMethods.setFast(true);
    }

    public static String[] generateFields(Object vo, Set<String> ban) {
        @SuppressWarnings("unchecked")
        Class clazz = vo.getClass();
        String key = clazz.getName();
        String[] fs = (String[]) fieldsMap.get(key);
        if (fs == null) {
            PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors(clazz);
            List<String> list = new ArrayList<String>();
            for (PropertyDescriptor pd : pds) {
                if (pd.getReadMethod() != null) {
                    String name = pd.getName();
                    if (name != null) {
                        if ((ban == null) || !ban.contains(name)) {
                            list.add(name);
                        }
                    }
                }
            }
            fs = new String[list.size()];
            fs = list.toArray(fs);
            fieldsMap.put(key, fs);
        }
        return fs;
    }

    public static Method propertyMethod(Object vo, String name) throws SecurityException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        String key = vo.getClass().getName();
        FastHashMap methods = (FastHashMap) allMethods.get(key);
        if (methods == null) {
            methods = new FastHashMap();
            methods.setFast(true);
            allMethods.put(key, methods);
        }
        Method method = (Method) methods.get(name);
        if (method == null) {
            method = PropertyUtils.getPropertyDescriptor(vo, name).getReadMethod();
            methods.put(name, method);
        }
        return method;
    }

    public static Object propertyValue(Object vo, String name) {
        try {
            return propertyMethod(vo, name).invoke(vo);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}
